package ai.easy.robot

import com.squareup.javapoet.ClassName
import com.squareup.javapoet.MethodSpec
import com.squareup.javapoet.TypeName
import com.squareup.javapoet.TypeSpec
import javax.lang.model.element.Modifier.*

/**
 * 生成Msg转换代码
 */
internal object MsgConvertorCodeGenerator {

    private val CLASS_NAME_PREFIX = "Convert"

    fun generateClass(msgClass: EasyMsgClass): TypeSpec {

        val className = msgClass.type.toString().split(".").last()

        val builder = TypeSpec.classBuilder(CLASS_NAME_PREFIX + className)
                .addModifiers(PUBLIC, FINAL)

        builder.addMethod(generateToBundleMethod(msgClass))

        builder.addMethod(generateToMsgMethod(msgClass))

        return builder.build()
    }

    inline fun MethodSpec.Builder.beginTry(add: Boolean) {
        if (add) {
            addCode("try {\n")
        }
    }

    inline fun MethodSpec.Builder.endTry(add: Boolean) {
        val TErr = ClassName.get("java.lang", "Exception")
        if (add) {
            addCode("} catch (\$T e) {\n" +
                    "   e.printStackTrace();\n" +
                    "}\n", TErr)
        }
    }

    private fun generateToMsgMethod(msgClass: EasyMsgClass): MethodSpec {

        val TBundle = ClassName.get("android.os", "Bundle")
        val TMsg = TypeName.get(msgClass.type)
        //
        val methodBuilder = MethodSpec.methodBuilder("toMsg")
                .addModifiers(PUBLIC, STATIC)
                .addParameter(TBundle, "b")
                .returns(TMsg)
                .addStatement("\$T r = new \$T()", TMsg, TMsg)

        methodBuilder.beginTry(msgClass.variableNames.isNotEmpty())

        for (variableName in msgClass.variableNames) {
            val t1 = when (variableName.second.toString()) {
                "java.lang.String" -> "String"
                "int" -> "Int"
                "long" -> "Long"
                "boolean" -> "Boolean"
                "double" -> "Double"
                "float" -> "Float"
                else -> ""
            }
            methodBuilder.addStatement(String.format("  r.%s = b.get%s(\"%s\")",
                    variableName.first, t1, variableName.first))

        }
        methodBuilder.endTry(msgClass.variableNames.isNotEmpty())

        methodBuilder.addStatement("return r")

        return methodBuilder.build()
    }

    /**
     *
     */
    private fun generateToBundleMethod(msgClass: EasyMsgClass): MethodSpec {

        val TBundle = ClassName.get("android.os", "Bundle")
        val paramName = msgClass.type.toString().split(".").last().toLowerCase()

        val methodBuilder = MethodSpec.methodBuilder("toBundle")
                .addModifiers(PUBLIC, STATIC)
                .addParameter(TypeName.get(msgClass.type), paramName)
                .addStatement("\$T b = new \$T()", TBundle, TBundle)
                .returns(TBundle)

        methodBuilder.beginTry(msgClass.variableNames.isNotEmpty())

        for (variableName in msgClass.variableNames) {
            val t1 = when (variableName.second.toString()) {
                "java.lang.String" -> "String"
                "int" -> "Int"
                "long" -> "Long"
                "boolean" -> "Boolean"
                "double" -> "Double"
                "float" -> "Float"
                else -> ""
            }
            methodBuilder.addStatement(String.format("  b.put%s(\"%s\", ${paramName}.%s)",
                    t1, variableName.first, variableName.first))

        }

        methodBuilder.endTry(msgClass.variableNames.isNotEmpty())

        methodBuilder.addStatement("return b")

        return methodBuilder.build()
    }
}
